// ===================================================================
// Author: Matt Kruse <matt@ajaxtoolbox.com>
// WWW: http://www.AjaxToolbox.com/
//
// NOTICE: You may use this code for any purpose, commercial or
// private, without any further permission from the author. You may
// remove this notice from your final code if you wish, however it is
// appreciated by the author if at least my web site address is kept.
//
// You may *NOT* re-distribute this code in any way except through its
// use. That means, you can include it in your product, or your web
// site, or any other form where the code is actually being used. You
// may not put the plain javascript up on your site for download or
// include it in your javascript libraries for download. 
// If you wish to share this code with others, please just point them
// to the URL instead.
// Please DO NOT link directly to my .js files from your site. Copy
// the files to your server and use them there. Thank you.
// ===================================================================

function AjaxRequest()
{
	var req = new Object();
	req.timeout = null;
	req.generateUniqueUrl = false;
	req.url = window.location.href;
	req.method = "GET";
	req.async = true;
	req.username = null;
	req.password = null;
	req.parameters = new Object();
	req.requestIndex = AjaxRequest.numAjaxRequests++;
	req.responseReceived = false;
	req.groupName = null;
	req.queryString = "";
	req.responseText = null;
	req.responseXML = null;
	req.status = null;
	req.statusText = null;
	req.aborted = false;
	req.xmlHttpRequest = null;
	req.onTimeout = null;
	req.onLoading = null;
	req.onLoaded = null;
	req.onInteractive = null;
	req.onComplete = null;
	req.onSuccess = null;
	req.onError = null;
	req.onGroupBegin = null;
	req.onGroupEnd = null;
	req.xmlHttpRequest = AjaxRequest.getXmlHttpRequest();
	if(req.xmlHttpRequest==null)
	{
		return null;
	}
	req.xmlHttpRequest.onreadystatechange = function()
	{
		if(req == null || req.xmlHttpRequest == null)
		{
			return;
		}
		if(req.xmlHttpRequest.readyState==1)
		{
			req.onLoadingInternal(req);
		}
		if(req.xmlHttpRequest.readyState==2)
		{
			req.onLoadedInternal(req);
		}
		if(req.xmlHttpRequest.readyState==3)
		{
			req.onInteractiveInternal(req);
		}
		if(req.xmlHttpRequest.readyState==4)
		{
			req.onCompleteInternal(req);
		}
	};
	req.onLoadingInternalHandled = false;
	req.onLoadedInternalHandled = false;
	req.onInteractiveInternalHandled = false;
	req.onCompleteInternalHandled = false;
	req.onLoadingInternal = function()
	{
		if(req.onLoadingInternalHandled)
		{
			return;
		}
		AjaxRequest.numActiveAjaxRequests++;
		if(AjaxRequest.numActiveAjaxRequests == 1 && typeof(window['AjaxRequestBegin']) == "function")
		{
			AjaxRequestBegin();
		}
		if(req.groupName != null)
		{
			if(typeof(AjaxRequest.numActiveAjaxGroupRequests[req.groupName]) == "undefined")
			{
				AjaxRequest.numActiveAjaxGroupRequests[req.groupName] = 0;
			}
			AjaxRequest.numActiveAjaxGroupRequests[req.groupName]++;
			if(AjaxRequest.numActiveAjaxGroupRequests[req.groupName]==1 && typeof(req.onGroupBegin) == "function")
			{
				req.onGroupBegin(req.groupName);
			}
		}
		if(typeof(req.onLoading) == "function")
		{
			req.onLoading(req);
		}
		req.onLoadingInternalHandled = true;
	};
	req.onLoadedInternal = function()
	{
		if(req.onLoadedInternalHandled)
		{
			return;
		}
		if(typeof(req.onLoaded) == "function")
		{
			req.onLoaded(req);
		}
		req.onLoadedInternalHandled=true;
	};
	req.onInteractiveInternal = function()
	{
		if(req.onInteractiveInternalHandled)
		{
			return;
		}
		if(typeof(req.onInteractive) == "function")
		{
			req.onInteractive(req);
		}
		req.onInteractiveInternalHandled = true;
	};
	req.onCompleteInternal = function()
	{
		if(req.onCompleteInternalHandled || req.aborted)
		{
			return;
		}
		req.onCompleteInternalHandled = true;
		AjaxRequest.numActiveAjaxRequests--;
		if(AjaxRequest.numActiveAjaxRequests == 0 && typeof(window['AjaxRequestEnd']) == "function")
		{
			AjaxRequestEnd(req.groupName);
		}
		if(req.groupName != null)
		{
			AjaxRequest.numActiveAjaxGroupRequests[req.groupName]--;
			if(AjaxRequest.numActiveAjaxGroupRequests[req.groupName] == 0 && typeof(req.onGroupEnd) == "function")
			{
				req.onGroupEnd(req.groupName);
			}
		}
		req.responseReceived = true;
		req.status = req.xmlHttpRequest.status;
		req.statusText = req.xmlHttpRequest.statusText;
		req.responseText = req.xmlHttpRequest.responseText;
		req.responseXML = req.xmlHttpRequest.responseXML;
		if(typeof(req.onComplete) == "function")
		{
			req.onComplete(req);
		}
		if(req.xmlHttpRequest.status == 200 && typeof(req.onSuccess) == "function")
		{
			req.onSuccess(req);
		}
		else if(typeof(req.onError) == "function")
		{
			req.onError(req);
		}
		delete req.xmlHttpRequest['onreadystatechange'];
		req.xmlHttpRequest = null;
	};
	req.onTimeoutInternal = function()
	{
		if(req != null && req.xmlHttpRequest != null && !req.onCompleteInternalHandled)
		{
			req.aborted = true;
			req.xmlHttpRequest.abort();
			AjaxRequest.numActiveAjaxRequests--;
			if(AjaxRequest.numActiveAjaxRequests == 0 && typeof(window['AjaxRequestEnd']) == "function")
			{
				AjaxRequestEnd(req.groupName);
			}
			if(req.groupName != null)
			{
				AjaxRequest.numActiveAjaxGroupRequests[req.groupName]--;
				if(AjaxRequest.numActiveAjaxGroupRequests[req.groupName]==0 && typeof(req.onGroupEnd)=="function")
				{
					req.onGroupEnd(req.groupName);
				}
			}
			if(typeof(req.onTimeout)=="function")
			{
				req.onTimeout(req);
			}
			delete req.xmlHttpRequest['onreadystatechange'];
			req.xmlHttpRequest =null;
		}
	};
	req.process = function()
	{
		if(req.xmlHttpRequest!=null)
		{
			if(req.generateUniqueUrl && req.method=="GET")
			{
				req.parameters["AjaxRequestUniqueId"] = new Date().getTime() + "" + req.requestIndex;
			}
			var content = null;
			for(var i in req.parameters)
			{
				if(req.queryString.length>0)
				{
					req.queryString += "&";
				}
				req.queryString += encodeURIComponent(i) + "=" + encodeURIComponent(req.parameters[i]);
			}
			if(req.method == "GET")
			{
				if(req.queryString.length > 0)
				{
					req.url += ((req.url.indexOf("?")>-1)?"&":"?") + req.queryString;
				}
			}
			req.xmlHttpRequest.open(req.method,req.url,req.async,req.username,req.password);
			if(req.method == "POST")
			{
				if(typeof(req.xmlHttpRequest.setRequestHeader) != "undefined")
				{
					req.xmlHttpRequest.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
				}
				content = req.queryString;
			}
			if(req.timeout > 0)
			{
				setTimeout(req.onTimeoutInternal,req.timeout);
			}
			req.xmlHttpRequest.send(content);
		}
	};
	req.handleArguments = function(args)
	{
		for(var i in args)
		{
			if(typeof(req[i])=="undefined")
			{
				req.parameters[i] =args[i];
			}
			else
			{
				req[i] =args[i];
			}
		}
	};
	req.getAllResponseHeaders = function()
	{
		if(req.xmlHttpRequest!= null)
		{
			if(req.responseReceived)
			{
				return req.xmlHttpRequest.getAllResponseHeaders();
			}
			alert("Cannot getAllResponseHeaders because a response has not yet been received");
		}
	};
	req.getResponseHeader = function(headerName)
	{
		if(req.xmlHttpRequest!= null)
		{
			if(req.responseReceived)
			{
				return req.xmlHttpRequest.getResponseHeader(headerName);
			}
			alert("Cannot getResponseHeader because a response has not yet been received");
		}
	};
	return req;
}

AjaxRequest.getXmlHttpRequest = function()
{
	if(window.XMLHttpRequest)
	{
		return new XMLHttpRequest();
	}
	else if(window.ActiveXObject)
	{
		/*@cc_on @*/
		/*@if(@_jscript_version >=5)
		try{return new ActiveXObject("Msxml2.XMLHTTP");}catch(e){try{return new ActiveXObject("Microsoft.XMLHTTP");}catch(E){return null;}}@end @*/
	}
	else
	{
		return null;
	}
};
AjaxRequest.isActive = function()
{
	return(AjaxRequest.numActiveAjaxRequests>0);
};
AjaxRequest.get = function(args)
{
	AjaxRequest.doRequest("GET",args);
};
AjaxRequest.post = function(args)
{
	AjaxRequest.doRequest("POST",args);
};
AjaxRequest.doRequest = function(method,args)
{
	if(typeof(args)!="undefined" && args!=null)
	{
		var myRequest = new AjaxRequest();
		myRequest.method = method;
		myRequest.handleArguments(args);
		myRequest.process();
	}
};
AjaxRequest.submit = function(theform, args)
{
	var myRequest = new AjaxRequest();
	if(myRequest == null)
	{
		return false;
	}
	var serializedForm = AjaxRequest.serializeForm(theform);
	myRequest.method =theform.method.toUpperCase();
	myRequest.url =theform.action;
	myRequest.handleArguments(args);
	myRequest.queryString =serializedForm;
	myRequest.process();
	return true;
};
AjaxRequest.serializeForm = function(theform)
{
	var els = theform.elements;
	var len = els.length;
	var queryString = "";
	this.addField = function(name,value)
	{
		if(queryString.length > 0)
		{
			queryString += "&";
		}
		queryString += encodeURIComponent(name) + "=" + encodeURIComponent(value);
	};
	for(var i=0;i<len;i++)
	{
		var el =els[i];
		if(!el.disabled)
		{
			switch(el.type)
			{
				case 'text': case 'password': case 'hidden': case 'textarea':
					this.addField(el.name,el.value);
					break;
				case 'select-one':
					if(el.selectedIndex>=0)
					{
						this.addField(el.name,el.options[el.selectedIndex].value);
					}
					break;
				case 'select-multiple':
					for(var j=0;j<el.options.length;j++)
					{
						if(el.options[j].selected)
						{
							this.addField(el.name,el.options[j].value);
						}
					}
					break;
				case 'checkbox': case 'radio':
					if(el.checked)
					{
						this.addField(el.name,el.value);
					}
					break;
			}
		}
	}
	return queryString;
};
AjaxRequest.numActiveAjaxRequests = 0;
AjaxRequest.numActiveAjaxGroupRequests = new Object();
AjaxRequest.numAjaxRequests = 0;

